<template>
    <WithWait :loading="loading">
        <div class="contentLayout">
            <!-- 搜索表单 -->
            <div class="formSearch">
                <SupperFrom :model="form" label-width="70px" :fileds="searchFileds" :option="searchOption" :inline="true"
                    @submit="find" />
            </div>
            <!-- 数据表格 -->
            <div class="contentView">
                <div class="actionList">
                    <el-button v-permission="'system:role:add'" type="primary" @click="add()">
                        <svg-icon name="add"></svg-icon>新 增</el-button>
                    <el-button v-permission="'system:role:edit'" type="success" @click="edit(table.rows![0])"
                        :disabled="!table.rows || table.rows && table.rows.length !== 1"><svg-icon name="edit"></svg-icon>修
                        改</el-button>
                    <el-button v-permission="'system:role:remove'" type="danger"
                        :disabled="!table.rows || table.rows && table.rows.length !== 1"
                        @click="isdelete(table.rows![0])"><svg-icon name="delete"></svg-icon>删 除</el-button>
                    <el-button v-if="sortActive" color="#626aef" @click="sort">
                        <svg-icon name="sorting"></svg-icon>排 序
                    </el-button>
                </div>
                <SupperTable :data="table.data" :column="tableColumn" @selection-change="selectionRows">
                    <template #status="scope">
                        <el-switch v-model="scope.row.status" @change="modify(scope.row)"></el-switch>
                    </template>
                    <template v-slot="{ row }">
                        <el-button v-if="row._id !== '100000000100000000000000'" v-permission="'system:role:edit'" circle
                            type="success" size="small" @click="edit(row)"><svg-icon name="edit"></svg-icon></el-button>
                        <el-button v-if="row._id !== '100000000100000000000000'" v-permission="'system:role:remove'" circle
                            type="danger" size="small" @click="isdelete(row)"><svg-icon
                                name="delete"></svg-icon></el-button>
                    </template>
                </SupperTable>
                <el-pagination background layout="total, sizes, prev, pager, next, jumper" :total="pages.total"
                    @size-change="sizeChange" @current-change="currentChange" v-model:current-page="pages.limit"
                    v-model:page-size="pages.size" :page-sizes="[10, 20, 50, 100]" />
            </div>
        </div>
        <!-- 弹出框操作 -->
        <el-dialog draggable :destroy-on-close="true" v-model="dialog.visible" :title="dialog.title" width="550">
            <SupperFrom ref="FormRef" :model="dialog.form" :fileds="roleFileds" :option="dialogOption" :rules="roleRules"
                :inline="false" @submit="submit" @cancel="dialog.visible = false" :label-width="'120px'" />
        </el-dialog>
    </WithWait>
</template>
<script lang="ts">

export default {
    name: "菜单管理"
}
</script>
<script lang='ts' setup>
import Sortable, { SortableEvent } from 'sortablejs'
import { Form } from "@/types/form"
import { Table } from "@/types/table"
import { Role } from '@/types/role';
import { appendRole, getRoleList, removeRole, updateRole } from '@/api/system/role';
import { handleResponse } from '@/utils/responseCode';
import { nextTick, reactive, ref, toRaw } from 'vue';
import { ElMessage, ElMessageBox, FormRules } from 'element-plus';
import { getMenuList } from "@/api/system/menu";
import SupperFrom from "@/components/Form/index.vue"
import SupperTable from "@/components/Table/index.vue"
import { Pagination } from "@/types/pagination"
import { Menu } from '@/types/menu';
// 页面加载loading
let loading = ref<boolean>(true)
// ===========搜索表单 start===========
let form = ref<Role.RoleSearchQuery>({
    rolename: ""
})
let FormRef = ref()
// 搜索表单配置项
const searchOption: Form.Options = {
    btnList: ["reset", "submit"]
}
// 搜索表单输入项
const searchFileds: Form.Fileds[] = [
    {
        label: "角色名称",
        type: "input",
        key: "rolename",
        placeholder: "请输入角色名称"
    },
    {
        label: "角色状态",
        type: "select",
        key: "status",
        placeholder: "请选择角色状态",
        option: [
            {
                label: "启用",
                value: true
            },
            {
                label: "禁用",
                value: false
            }
        ]
    },
    {
        label: "创建时间",
        type: "date",
        key: "createTime",
        placeholder: "请选择角色创建时间"
    },
    {
        label: "描述",
        type: "input",
        key: "describe",
        placeholder: "请输入角色名称"
    },
]
// ===========搜索表单 end=============

// ===========增加、修改表单配置项 start=

interface DialogProps {
    title: "新增" | "修改",
    visible: boolean,
    form: Role.Role
}
// 新增、修改操作
const dialog = reactive<DialogProps>({
    title: "新增",
    visible: false,
    form: {
        rolename: "",
        status: true
    },
})
const dialogOption: Form.Options = {
    btnList: ["cancel", "submit"]
}
// 操作表单
const roleFileds = ref<Form.Fileds[]>([
    {
        label: "角色名称", // 名称
        type: "input", // 表单类型
        key: "rolename", // key
        placeholder: "请输入角色名称", // 提示文字
    },
    {
        label: "角色状态", // 名称
        type: "select", // 表单类型
        key: "status", // key
        placeholder: "请选择角色状态", // 提示文字
        option: [
            { label: "启用", value: true },
            { label: "禁用", value: false },
        ]
    },
    {
        label: "描述",
        type: "input",
        key: "describe", // key
        placeholder: "请输入描述", // 提示文字
    },
    {
        label: "菜单权限", // 名称
        type: "tree", // 表单类型
        key: "menus", // key
        placeholder: "请选择菜单权限", // 提示文字
        option: [],
    }
])
// 表单规则
const roleRules: FormRules = {

    rolename: [
        { required: true, message: '请输入角色名称', trigger: 'blur' },
        { min: 2, max: 10, message: '菜单名称请控制在3-10个字符', trigger: 'blur' },
    ],
    status: [
        { required: true, message: "请选择菜单状态", trigger: "blur" }
    ],
}
// 表单提交事件
const submit = () => {
    dialog.form.menus = FormRef.value.getCheckedKeys()

    if (dialog.title === "新增") {
        append(dialog.form)
    }
    if (dialog.title === "修改") {
        modify(dialog.form)
    }
    dialog.visible = false
}
// ===========增加、修改表单配置项 end==============

// ===========表格操作 start=====================
let sortActive = ref<boolean>(false)
interface TableProps {
    data: Role.Role[],
    rows: Role.Role[] | undefined,
}
// 表格项配置
const tableColumn: Table.Column[] = [
    {
        prop: "rolename",
        label: "角色名称",
        minWidth: '150px'
    },
    {
        prop: "status",
        label: "角色状态",
        slot: true,
    },
    {
        prop: "createTime",
        label: "创建时间",
        minWidth: '150px'
    },
    {
        prop: "describe",
        label: "描述",
    },
]
// 表格
const table = reactive<TableProps>({
    data: [],
    rows: undefined
})
const add = async () => {
    let res = await getMenuList()
    dialog.title = "新增"
    roleFileds.value[roleFileds.value.length - 1].option = res.data.data
    dialog.form = {
        rolename: "",
        status: true
    }
    dialog.visible = true
}
const edit = async (row: Role.Role) => {
    dialog.form = row
    dialog.title = "修改"
    let res = await getMenuList()
    roleFileds.value[roleFileds.value.length - 1].option = res.data.data
    dialog.visible = true
    nextTick(() => {
        if (dialog.form.menus?.length === 0) return

        const getChildKeys = (data: Menu.TreeMenuList[], arr: string[], newarr: Menu.TreeMenuList[] = []): Menu.TreeMenuList[] => {
            for (let i = 0; i < data.length; i++) {
                const item = data[i];
                if (arr.includes(item._id!)) {
                    newarr.push(item)
                }
                item.children && getChildKeys(item.children, dialog.form.menus!, newarr)
            }
            return newarr
        }

        let d = getChildKeys(res.data.data as Menu.TreeMenuList[], dialog.form.menus!)

        let result = d.map(item => item.children ? false : item._id).filter(Boolean)

        FormRef.value.setCheckedKeys(result)
    })
}
const isdelete = (row: Role.Role) => {
    ElMessageBox.confirm(
        `是否删除 ${row.rolename} ？`,
        '警告',
        {
            confirmButtonText: '删除',
            cancelButtonText: '取消',
            type: 'warning',
            draggable: true,
        }
    ).then(() => {
        row._id && remove(row._id!)
    })

}
const sort = async () => {
    loading.value = true
    try {
        let obj = {
            type: "sort",
            data: toRaw(table.data)
        }
        let res = await updateRole(obj)
        const { msg, code } = res.data
        if (!handleResponse(code, msg)) return loading.value = false
        ElMessage.success("排序修改成功")
        loading.value = false
        sortActive.value = false
    } catch (error) {
        loading.value = false
        handleResponse("500", "接口请求失败")
    }

}
const selectionRows = (rowlist: Role.Role[]) => {
    table.rows = rowlist
}
// ===========表格操作 end=============

// ===========接口方法 start===========
// 查找
const find = async (query?: Role.RoleSearchQuery) => {
    loading.value = true
    try {
        let res = await getRoleList(pages, query)
        const { data, msg, code, total } = res.data
        if (!handleResponse(code, msg)) return loading.value = false
        table.data = data
        pages.total = total
        loading.value = false
    } catch (error) {
        loading.value = false
        handleResponse("500", "接口请求失败")

    }

}
// 新增
const append = async (query: Role.Role) => {
    try {
        loading.value = true
        let res = await appendRole(query)
        const { msg, code } = res.data
        if (!handleResponse(code, msg)) return loading.value = false;
        ElMessage.success("新增成功")
        find()
    } catch (error) {
        handleResponse("500")
    }
}
// 修改
const modify = async (query: Role.Role) => {
    if (query._id === "64083b4cc94e5ceabacb4b52") return query.status = true
    try {
        loading.value = true
        let res = await updateRole(query)
        const { msg, code } = res.data
        if (!handleResponse(code, msg)) return loading.value = false;
        ElMessage.success("修改成功")
        find()
    } catch (error) {
        handleResponse("500", "服务器异常")
    }
}
// 删除
const remove = async (id: string) => {
    try {
        let res = await removeRole(id)
        const { msg, code } = res.data
        if (!handleResponse(code, msg)) return loading.value = false;
        ElMessage.success("删除成功")
        find()
    } catch (error) {
        handleResponse("500")
    }
}
// ===========接口方法 end= ============


// ===========分页 start ===============
const pages = reactive<Pagination.Pagination>({
    size: 10, // 条目
    limit: 1, // 页码
    total: 0,// 总条目
})
const sizeChange = () => find(form.value)
const currentChange = () => find(form.value)
// ===========分页 end =================
find()

// 排序
const initSortable = () => {
    // 获取表格row的父节点
    const tableElement = document.querySelector('.el-table__body-wrapper tbody') as HTMLElement
    // 创建拖拽实例
    Sortable.create(tableElement, {
        animation: 550, //动画
        disabled: false, // 拖拽不可用? false 启用（刚刚渲染表格的时候起作用，后面不起作用）
        // 结束拖动事件
        onEnd: (event: SortableEvent) => {
            sortActive.value = true
            const { oldIndex, newIndex } = event;
            [table.data[newIndex!].sort, table.data[oldIndex!].sort] = [table.data[oldIndex!].sort, table.data[newIndex!].sort];
            [table.data[newIndex!], table.data[oldIndex!]] = [table.data[oldIndex!], table.data[newIndex!]];
        },
    })
}
nextTick(() => {
    initSortable()
})

</script>
<style lang="less" scoped></style>